﻿using System.Security.Principal;

namespace Centrify.DirectAudit.AuditDatabase.StoredProcedures
{
    using System;
    using System.Data;
    using System.Data.SqlClient;
    using Centrify.DirectAudit.AuditDatabase.Tables;
    using Centrify.DirectAudit.Common.SqlClr;
    using Microsoft.SqlServer.Server;

    public class DatabaseGuidGet : AuditDatabaseStoredProcedure<
        DatabaseGuidGet,
        DatabaseGuidGet.Input,
        DatabaseGuidGet.Output,
        DatabaseGuidGet.Variables>
    {
        #region Mapping definition

        public enum Variables : int
        {
            [Variable(Direction.Output)]
            Guid
        }

        public struct Input
        {
        }

        public struct Output
        {
            [OutputMapping((int)Variables.Guid, SqlDbType.UniqueIdentifier)]
            public Guid Guid;
        }
        #endregion

        [StoredProcedure(ExecuteAs = WellKnownSidType.LocalSystemSid, ExecuteBy = "managementdb,setup_user")]
        public static void StoredProcedure(out Guid guid)
        {
            string sql = Build("SELECT", Variables.Guid, 
                               "= CAST(value AS UNIQUEIDENTIFIER) FROM sys.extended_properties WHERE name =",
                               QuoteCharUnicode(ExtendedPropertyName.AUDIT_STORE_DATABASE_GUID));
            using (SqlCommand command = CreateCommand(sql))
            {
                command.Parameters.AddRange(Parameters(new Input()));
                SqlContext.Pipe.ExecuteAndSend(command);
                guid = Guid.Empty;
                command.GetValue(Variables.Guid, ref guid);
            }
        }
    }

    public class DatabaseGuidSet : AuditDatabaseStoredProcedure<
       DatabaseGuidSet,
       DatabaseGuidSet.Input,
       DatabaseGuidSet.Output,
       DatabaseGuidSet.Variables>
    {
        #region Mapping definition

        public enum Variables : int
        {
            [Variable(Direction.Input)]
            Guid
        }

        public struct Input
        {
            [InputMapping((int)Variables.Guid)]
            public Guid Guid;

            public Input(Guid guid)
            {
                Guid = guid;
            }
        }

        public struct Output
        {
        }
        #endregion

        [StoredProcedure(ExecuteAs = WellKnownSidType.LocalSystemSid, ExecuteBy = "managementdb,setup_user")]
        public static void StoredProcedure(string clientVersion, Guid guid)
        {
            CheckVersion(clientVersion);

            string sql = Build("EXEC sp_addextendedproperty @name=", 
                               QuoteCharUnicode(ExtendedPropertyName.AUDIT_STORE_DATABASE_GUID),
                               ", @value=", Variables.Guid);
            using (SqlCommand command = CreateCommand(sql))
            {
                command.Parameters.AddRange(Parameters(new Input(guid)));
                SqlContext.Pipe.ExecuteAndSend(command);
            }
        }
    }

    public class DatabaseInstallationGet : AuditDatabaseStoredProcedure<
       DatabaseInstallationGet,
       DatabaseInstallationGet.Input,
       DatabaseInstallationGet.Output,
       DatabaseInstallationGet.Variables>
    {
        #region Mapping definition

        public enum Variables : int
        {
            [Variable(Direction.Output)]
            InstallationName
        }

        public struct Input
        {
        }

        public struct Output
        {
            [OutputMapping((int)Variables.InstallationName, SqlDbType.NVarChar, 64)]
            public string InstallationName;
        }
        #endregion

        [StoredProcedure(ExecuteAs = WellKnownSidType.LocalSystemSid, ExecuteBy = "managementdb,setup_user")]
        public static void StoredProcedure(out string installationName)
        {
            string sql = Build("SELECT", Variables.InstallationName,
                               "FROM sys.extended_properties WHERE name =",
                               QuoteCharUnicode(ExtendedPropertyName.AUDIT_STORE_DATABASE_INSTALLATION));
            using (SqlCommand command = CreateCommand(sql))
            {
                command.Parameters.AddRange(Parameters(new Input()));
                SqlContext.Pipe.ExecuteAndSend(command);
                installationName = string.Empty;
                command.GetValue(Variables.InstallationName, ref installationName);
            }
        }
    }

    public class DatabaseInstallationSet : AuditDatabaseStoredProcedure<
       DatabaseInstallationSet,
       DatabaseInstallationSet.Input,
       DatabaseInstallationSet.Output,
       DatabaseInstallationSet.Variables>
    {
        #region Mapping definition

        public enum Variables : int
        {
            [Variable(Direction.Input)]
            InstallationName
        }

        public struct Input
        {
            [InputMapping((int)Variables.InstallationName)]
            public string InstallationName;

            public Input(string installationName)
            {
                InstallationName = installationName;
            }
        }

        public struct Output
        {
        }
        #endregion

        [StoredProcedure(ExecuteAs = WellKnownSidType.LocalSystemSid, ExecuteBy = "managementdb,setup_user")]
        public static void StoredProcedure(string clientVersion, string installationName)
        {
            CheckVersion(clientVersion);

            string sql = Build("EXEC sp_addextendedproperty @name=",
                               QuoteCharUnicode(ExtendedPropertyName.AUDIT_STORE_DATABASE_INSTALLATION),
                               ", @value=", Variables.InstallationName);
            using (SqlCommand command = CreateCommand(sql))
            {
                command.Parameters.AddRange(Parameters(new Input(installationName)));
                SqlContext.Pipe.ExecuteAndSend(command);
            }
        }
    }

    public class DatabaseInstallationUpdate : AuditDatabaseStoredProcedure<
       DatabaseInstallationUpdate,
       DatabaseInstallationUpdate.Input,
       DatabaseInstallationUpdate.Output,
       DatabaseInstallationUpdate.Variables>
    {
        #region Mapping definition

        public enum Variables : int
        {
            [Variable(Direction.Input)]
            InstallationName
        }

        public struct Input
        {
            [InputMapping((int)Variables.InstallationName)]
            public string InstallationName;

            public Input(string installationName)
            {
                InstallationName = installationName;
            }
        }

        public struct Output
        {
        }
        #endregion

        [StoredProcedure(ExecuteAs = WellKnownSidType.LocalSystemSid, ExecuteBy = "managementdb,setup_user")]
        public static void StoredProcedure(string clientVersion, string installationName)
        {
            CheckVersion(clientVersion);

            string sql = Build("EXEC sp_updateextendedproperty @name=",
                               QuoteCharUnicode(ExtendedPropertyName.AUDIT_STORE_DATABASE_INSTALLATION),
                               ", @value=", Variables.InstallationName);
            using (SqlCommand command = CreateCommand(sql))
            {
                command.Parameters.AddRange(Parameters(new Input(installationName)));
                SqlContext.Pipe.ExecuteAndSend(command);
            }
        }
    }
}
